package diplom

import com.qc.Builds
import com.qc.Files
import com.qc.Reports
import groovy.io.FileType

class ResultingService {
    def TEST_DIR = "d:\\lucky\\lucky\\grails-app\\controllers\\"
    def TEST_PROJECT_NAME = "projectName"
    def TARGET_EXTENSION = '.groovy'


    Builds createTestData() {
        Builds analysis = newAnalysis()
        new File(TEST_DIR).eachFileRecurse(FileType.FILES) { file ->
            if (file.name.contains(TARGET_EXTENSION)) {
                createResult(file, analysis)

            }
        }
        return analysis

    }

    private Builds newAnalysis() {
        def analysis = new Builds()
        analysis.save()
        analysis
    }

     Reports createResult(File file, Builds build) {
        def dbFile = updateOrCreateFileInDB(file)
        def attrs = bringLocAttributes(file)
        def result = new Reports(file: dbFile, analysis: build)
        result.loc = attrs.sloc
        result.comments = attrs.cloc
         result.eloc =attrs.eloc
         result.lcom = attrs.lcom
         result.complexity = attrs.comp
         result.avgComplexity = attrs.complAvg
         result.favg = attrs.favg
         saveResult(result, build)
        return result
    }

    private saveResult(Reports result, Builds build) {
        if (!result.save()) {
            log.error(result.errors)
        } else {
            addToBuild(build, result)
        }
    }

    private addToBuild(Builds build, Reports result) {
        if (!build.reports) {
            build.reports = []
        }
        build.reports.add(result)
    }

    Files updateOrCreateFileInDB(File file) {
        def dbFile = Files.findByFullPath(file.canonicalPath)
        if (!dbFile) {
            dbFile = new Files()
            dbFile.fullPath = file.canonicalPath
            dbFile.name = file.name
            dbFile.save()
        }
        return dbFile
    }

    def bringLocAttributes(File file){
        int loc = 0
        int emptyLines = 0
        int comments = 0
        int openedBlocks = 0
        boolean multiLineComment = false
        def functions = 0
        def functionLine = 0
        def functionNames = [:]
        def filedNames = []
        def s = ""
        s += "<pre>"
        def complexity = 0
        def last = ""
        def related = 0
        def notRelated = 0
        file.eachLine {
            def dontCount = false
            if (it.contains('*/')) {
                multiLineComment = false
                dontCount = true
            }
            if (it.contains('/*')) {
                multiLineComment = true
                dontCount = true
                comments++
            } else if (it.length() == 0) {
                emptyLines++
                dontCount = true
            } else  if (it.contains('//')) {
                comments++
                dontCount = true
            }
            if (it.contains('{')) {
                if (openedBlocks == 1) {
                    functions++
                    def words = it.split(' ').findAll {!['private', 'static', 'public', 'protected', ''].contains(it)}
                    functionNames.put([words[1], []])
                    last = words[1]

                }
                openedBlocks++
            } else if (openedBlocks == 1 && !dontCount && !multiLineComment) {
                def wordss =  it.split(' ').findAll {!['private', 'static', 'public', 'protected', ''].contains(it)}
                if (wordss[1]) {
                    filedNames << wordss[1]
                }
            } else if (openedBlocks >= 2 && !dontCount && !multiLineComment) {
                def line = it
                filedNames.each {
                    if (line.contains(it))  {
                        functionNames[last] << it
                    }
                    ['if', 'else', '?.', 'each{', '*.', '||', '&&' ].each {
                        if (line.contains(it)) {
                            complexity++
                        }
                    }
                }
            }
            if (openedBlocks >= 2) {
                functionLine++
            }
            if (it.contains('}')) {
                openedBlocks--
            }
            if (multiLineComment && !it.length()) {
                comments++
            }
            loc++
            s +=  it

        }
        functionNames.each {name1 ->
            def r = false
            functionNames.each {name2 ->
                if (name1 != name2)
                    name1.each {it1 ->
                        name2.each{it2 ->
                            if (it1 == it2) {
                                r= true
                            }
                        }
                    }
            }
            if (r) {
                related++

            } else {
                notRelated++
            }

        }


        return [lcom: related, comp: complexity, complAvg: complexity / functionNames.size(),  favg: functions ? functionLine/functions : 0, loc: loc, eloc: emptyLines, cloc: comments, sloc: loc - emptyLines - comments]
    }

    Files updateOrCreateFileInDB(String path, String name) {
        Files dbFile
        if (name.contains('.groovy')) {
            dbFile = Files.findByFullPath(path)
            if (!dbFile) {
                dbFile = new Files()
                dbFile.fullPath = path
                dbFile.name = name
                dbFile.save()
            }
        }

        return dbFile  //To change body of created methods use File | Settings | File Templates.
    }
/*

    def xmlParsing(){
        Builds analysis = newAnalysis()
        def records = new XmlParser().parse("c:\\codeNarc.xml")
        records.depthFirst().Package.each {
            def filePath = it.attributes().path
            it.File.each {
                def fileName = it.attributes().name
                def file = updateOrCreateFileInDB(filePath, fileName)
                if (file) {
                    it.Violation.each {
                        def lineNumber = it.attributes().lineNumber
                        def ruleName = it.attributes().ruleName.toString()
                        def messageText = it.Message.text()

                        def styleRule = createOrGetExistingStyleRule(ruleName)
                        def styleError = new StyleError(message: messageText, file: file, line: lineNumber, styleRule: styleRule).save()
                        attachError(styleRule, file, styleError)
                    }
                }
            }
        }
    }
*/

}
